import array
import os

import pyuca
from unicodedata import normalize, name, numeric
import re
import locale

# 1、字符问题
s = 'café'
print(len(s))
b = s.encode('utf-8')  # 编码成bytes对象
print(b)
print(len(b))
print(b.decode('utf-8'))  # 解码成str对象
# 2、字节概要
cafe = bytes('café', 'utf-8')
print(cafe)
print(cafe[0])  # range(256) 内的整数
print(cafe[:1])  # 切片是 bytes 对象
cafe_arr = bytearray(cafe)
print(cafe_arr)
print(cafe_arr[-1:])  # bytearray 对象
print(bytes.fromhex('31 4B CE A9'))  # 解析16进制数字
# 使用数组的原始数据初始化bytes对象
numbers = array.array('h', [-2, -1, 0, 1, 2])  # h 短整数
octets = bytes(numbers)
print(octets)
# 3、基本的编解码器
for codec in ['latin_1', 'utf_8', 'utf_16']:
    print(codec, 'El Niño'.encode(codec), sep='\t')
# 4、了解编解码问题
# 处理UnicodeEncodeError
city = 'São Paulo'
print(city.encode('utf-8'))
print(city.encode('utf-16'))
print(city.encode('iso8859_1'))
# print(city.encode('cp437')) # UnicodeEncodeError
print(city.encode('cp437', errors='ignore'))  # 跳过
print(city.encode('cp437', errors='replace'))  # ? 号替换
print(city.encode('cp437', errors='xmlcharrefreplace'))  # 替换xml实体
# 处理UnicodeEncodeError
octets = b'Montr\xe9al'  # latin1编码的Montréal
print(octets.decode('cp1252'))  # cp1252是latin1的超集 可以解码
print(octets.decode('iso8859_1'))  # 希腊文 python3.9版本可以
print(octets.decode('koi8-r'))  # 俄文
# print(octets.decode('utf_8')) #UnicodeDecodeError
print(octets.decode('utf_8', errors='replace'))  # �替换未知字符
# SyntaxError py文件编码不是utf-8
# 找出字节序列的编码 chardet包
# 5、处理文本文件 @see file-test.py  default-encodings.py
# 6 为了正确比较而规范化Unicode字符串
s1 = 'café'
s2 = 'cafe\u0301'
print((s1, s2))
print(len(s1), len(s2))
print(s1 == s2)
# unicodedata.normalize 函数提供的Unicode规范化
# NFC 使用最少的码位构成等价的字符串
# NFD 把组合字符分解成基字符和单独的组合字符
print(len(normalize('NFC', s1)), len(normalize('NFC', s2)))
print(len(normalize('NFD', s1)), len(normalize('NFD', s2)))
print(normalize('NFC', s1) == normalize('NFC', s2))
print(normalize('NFD', s1) == normalize('NFD', s2))
# 电阻的单位欧姆（Ω）会被规范成希腊字母大写的欧米加
ohm = '\u2126'
print(name(ohm))
ohm_c = normalize('NFC', ohm)
print(name(ohm_c))
print(ohm == ohm_c)
print(normalize('NFC', ohm) == normalize('NFC', ohm_c))
# 两个规范化形式（NFKC 和 NFKD）的首字母缩略词中，字母 K表示“compatibility”（兼容性）。
# 这两种是较严格的规范化形式，对“兼容字符”有影响。
half = '½'
print(normalize('NFKC', half))
four_squared = '4²'
print(normalize('NFKC', four_squared))
micro = 'µ'
micro_kc = normalize('NFKC', micro)
print(micro, micro_kc)
print(ord(micro), ord(micro_kc))
print(name(micro), name(micro_kc), sep=',')
# 大小写折叠
micro = 'µ'
print(name(micro))
micro_cf = micro.casefold()
print(name(micro_cf))
print(micro, micro_cf)
eszett = 'ß'
print(name(eszett))
eszett_cf = eszett.casefold()
print(eszett, eszett_cf)

# 7、Unicode文本排序
# 非 ASCII 文本的标准排序方式是使用 locale.strxfrm函数
fruits = ['caju', 'atemoia', 'cajá', 'açaí', 'acerola']
print(sorted(fruits))

# 区域设置是全局的，因此不推荐在库中调用 setlocale 函数。
# 应用或框架应该在进程启动时设定区域设置，而且此后不要再修改
# locale.setlocale(locale.LC_COLLATE, 'pt_BR.UTF-8')
# sorted_fruits = sorted(fruits, key=locale.strxfrm)
# print(sorted_fruits)
# PyUCA 库
coll = pyuca.Collator()
sorted_fruits = sorted(fruits, key=coll.sort_key)
print(sorted_fruits)
# 8、Unicode数据库
re_digit = re.compile(r'\d')
sample = '1\xbc\xb2\u0969\u136b\u216b\u2466\u2480\u3285'
for char in sample:
    print('U+%04x' % ord(char),  # U+0000 格式的码位
          char.center(6),  # 在长度为 6 的字符串中居中显示字符
          're_dig' if re_digit.match(char) else '  -  ',
          'isdig' if char.isdigit() else '  -  ',
          'isnum' if char.isnumeric() else '  -  ',
          format(numeric(char), '5.2f'),  # 使用长度为 5、小数点后保留 2 位的浮点数显示数值
          name(char),
          sep='\t')

# 9、支持字符串和字节序列的双模式API @see ramanujan.py
print(os.listdir())